<!-- 商品管理-属性管理 -->
<template>
    <Category :show="show" />
    <div>
        <!--
            v-if：在条件首次为true时会有更高的初始渲染成本，因为需要创建DOM元素。当条件频繁切换时，反复的DOM销毁和重建会带来较高的性能消耗。
            v-show：初始渲染成本较低，因为元素始终存在于DOM中，仅通过CSS属性控制显示和隐藏。在条件频繁切换时性能更好，因为不涉及DOM元素的创建和销毁。
         -->
        <!-- 属性值显示 -->
        <el-card v-show="!show" style="margin: 10px 0">
            <el-button type="primary" icon="Plus" @click="addAttr" :disabled="!categoryStore.c3" v-hasButton="'add'">添加属性</el-button>
            <el-table :data="attrArr" style="margin: 10px 0;" border>
                <el-table-column label="序号" type="index" width="80px" align="center"></el-table-column>
                <el-table-column label="属性名称" prop="attrName" width="120px"></el-table-column>
                <el-table-column label="属性值名称">
                    <!-- 遍历显示属性值 -->
                    <template #="{ row, $index }">
                        <el-tag v-for="(attr, index) in row.attrValueList" :key="attr.id" type="primary"
                            style="margin: 5px">
                            {{ attr.valueName }}</el-tag>
                    </template>
                </el-table-column>
                <el-table-column label="操作" width="120px">
                    <template #="{ row, $index }">
                        <!-- 点击修改属性 -->
                        <el-button type="warning" size="small" icon="Edit" @click="onEditButton(row)" title="修改属性" v-hasButton="'update'"></el-button>
                        <!-- 点击删除属性 -->
                        <el-popconfirm :title="`确认删除“${row.attrName}”`" @confirm="onDeleteAttr(row.id)" width="auto">
                            <template #reference>
                                <el-button type="danger" size="small" icon="Delete" title="删除属性" v-hasButton="'remove'"></el-button>
                            </template>
                        </el-popconfirm>
                    </template>
                </el-table-column>
            </el-table>
        </el-card>

        <!-- 属性值添加 -->
        <el-card v-show="show" style="margin: 10px 0">
            <el-form>
                <el-form-item label="属性名称">
                    <!-- .trim 去除空白格 -->
                    <el-input placeholder="请输入属性名" style="width: 200px" v-model.trim="inputAttrName"
                        maxlength="13"></el-input>
                </el-form-item>
            </el-form>
            <!-- 当属性名为空 / 属性值列表最后一个为空 则 禁用“添加属性值”按钮 -->
            <el-button type="primary" icon="Plus" :disabled="!inputAttrName || attrParam.attrValueList.length
                && !attrParam.attrValueList.at(-1)?.valueName" @click="addAttrValue">添加属性值</el-button>
            <!-- <el-button>取消</el-button> -->
            <!-- table显示待添加的属性值 -->
            <el-table border style="margin: 15px 0" :data="attrParam.attrValueList">
                <el-table-column label="序号" type="index" width="80px" align="center"></el-table-column>
                <el-table-column label="属性值" prop="valueName">
                    <!-- v-show用flag控制当前哪个显示input，表示正在编辑，其他显示div -->
                    <template #="{ row, $index }">
                        <!-- ref获取实例 -->
                        <el-input :ref="(vc: any) => inputArr[$index] = vc" size="small" v-show="row.flag"
                            v-model.trim="row.valueName" placeholder="请输入属性值"
                            @blur="onBlurAttrValue(row, $index)"></el-input>
                        <div v-show="!row.flag" @click="onClickEdit(row, $index)">{{ row.valueName }}</div>
                    </template>
                </el-table-column>
                <el-table-column label="操作" width="120px">
                    <template #="{ row, $index }">
                        <!-- 删除待添加的属性值 -->
                        <el-button type="danger" icon="Delete" size="small"
                            @click="attrParam.attrValueList.splice($index, 1)"></el-button>
                    </template>
                </el-table-column>
            </el-table>
            <el-button type="primary" @click="saveAttr"
                :disabled="!(attrParam.attrValueList.length && attrParam.attrValueList[0].valueName)">保存</el-button>
            <el-button @click="show = false">取消</el-button>
        </el-card>
    </div>
</template>

<script setup lang="ts">
import useCategoryStore from '@/store/modules/category';
import { watch, ref, reactive, nextTick, onBeforeUnmount } from 'vue';
import { reqAttr, reqAddUpdateAttr, reqDeleteAttr } from '@/api/product/attr'
import type { AttrResData, Attr, AttrValue } from '@/api/product/attr/type'
import { ElMessage } from 'element-plus';
let categoryStore = useCategoryStore()
let attrArr = ref<Attr[]>([])
let emptyAttrParam = {
    attrName: "", // 属性名 
    attrValueList: [], // 属性值数组
    categoryId: '', // 第三级分类ID
    categoryLevel: 3, // 代表是第三级分类
}
let attrParam = reactive<Attr>({ ...emptyAttrParam });
// 三级分类true锁定、false显示table属性列表、true“添加属性”框显示
let show = ref<boolean>(false)
// "添加属性"的input组件内容
let inputAttrName = ref('')
// 存放input实例
let inputArr = ref<any>([])

// 以下是根据分类显示属性的el-card
// 卸载时清空原数据（清除上次获取的选项和数据）
onBeforeUnmount(() => {
    categoryStore.$reset();
    // categoryStore.c1 = categoryStore.c2 = categoryStore.c3 = '';
    // categoryStore.c1Arr = categoryStore.c2Arr = categoryStore.c3Arr = [];
})

// 监听第三个下拉选项是否变化
watch(() => categoryStore.c3, async () => {
    // 清空table
    attrArr.value = []
    // 保证三级分类，再发请求
    if (!categoryStore.c3) return;
    getAttr();
})

// 发送请求，获取table属性值数据
const getAttr = async () => {
    let { c1, c2, c3 } = useCategoryStore();
    let result: AttrResData = await reqAttr(c1 as number, c2 as number, c3 as number);
    if (result.code == 200)
        attrArr.value = result.data;
}

// 点击“添加属性”按钮
const addAttr = () => {
    // 隐藏属性表格
    show.value = true
    // 清空input
    inputAttrName.value = ''
    // 每次点击添加属性，先清空attrParam（浅拷贝，数组引用的是地址，需要清空数组）
    attrParam = reactive<Attr>({ ...emptyAttrParam })
    // 获取属性名称
    attrParam.categoryId = categoryStore.c3
    attrParam.attrValueList = []
    // attrParam = reactive<Attr>({
    //     attrName: "", // 属性名 
    //     attrValueList: [], // 属性值数组
    //     categoryId: categoryStore.c3, // 第三级分类ID
    //     categoryLevel: 3, // 代表是第三级分类
    // })
}

// 点击属性行的编辑按钮
const onEditButton = (row: Attr) => {
    // 显示属性编辑的el-card
    show.value = true
    // ES6功能，将row合并到attrParam，注意要深拷贝。先JSON变string，再string变JSON
    // 此处合并会同时得到属性的ID，发送请求时，若存在ID，则服务器实现的功能为“修改属性”
    Object.assign(attrParam, JSON.parse(JSON.stringify(row)));
    inputAttrName.value = attrParam.attrName
}

// 点击删除属性行
const onDeleteAttr = async (attrid: number) => {
    // 发送删除请求
    let result = await reqDeleteAttr(attrid);
    if (result.code == 200) {
        ElMessage.success('删除成功')
        getAttr();
    }
    else {
        ElMessage.error('删除失败')
    }
}

// 以下是“添加”/“修改”属性的el-card
// 添加属性值
const addAttrValue = () => {
    // 添加空属性值
    attrParam.attrValueList.push({
        valueName: '',
        flag: true  // 控制每一行属性值编辑模式的显示
    })

    // 获取最后一个input组件聚焦
    nextTick(() => {
        inputArr.value.at(-1).focus();
    })
}

// 保存属性（发送请求，保存到服务器）
const saveAttr = async () => {
    if (!inputAttrName.value) {
        ElMessage.error('属性名不能为空')
        return;
    }
    attrParam.attrName = inputAttrName.value
    // 提交
    let result: any = await reqAddUpdateAttr(attrParam);
    // 添加成功
    if (result.code == 200) {
        // 返回
        show.value = false
        ElMessage.success(attrParam.id ? '修改成功' : '添加成功')
        // 重新获取已有属性值
        getAttr();
    }
    // 添加失败
    else {
        ElMessage.error(attrParam.id ? '修改失败' : '添加失败')
    }
}

// 属性值input失焦
const onBlurAttrValue = (row: AttrValue, $index: number) => {
    // 非法情况1：属性值为空
    if (row.valueName.trim() == '') {
        // 在列表中删除
        attrParam.attrValueList.splice($index, 1);
        // 提示错误信息
        ElMessage.error('属性值不能为空')
    }

    // 非法情况二：重复值
    // some函数存在则返回boolean值，find返回第一个符合条件的值
    let repeat = attrParam.attrValueList.some((item) => {
        // 去除当前blur元素本身
        if (item != row)
            return item.valueName == row.valueName
    })

    if (repeat) {
        ElMessage.error('属性值不能重复')
        // 在列表中删除
        attrParam.attrValueList.splice($index, 1);
    }
    else
        // 属性值input失焦
        row.flag = false
}

// 点击属性值，显示input并聚焦
const onClickEdit = (row: AttrValue, $index: number) => {
    // 使row获得焦点
    row.flag = true
    // DOM更新后再聚焦
    nextTick(() => {
        inputArr.value[$index].focus();
    })
}

// 不使用pinia的属性table显示（不包含添加属性功能）
// import { ref } from 'vue'
// import type { AttrResData, Attr } from '@/api/product/attr/type'
// import { reqAttr } from '@/api/product/attr'
// let attrArr = ref<Attr[]>([])
// let showAddButton = ref<boolean>(false)
// // 获取表格数据
// async function getCategory(c1: number, c2: number, c3: number) {
//     showAddButton.value = true;
//     let result: AttrResData = await reqAttr(c1, c2, c3);
//     if (result.code == 200)
//         attrArr.value = result.data;
// }
// // 清空表格数据（根据子组件返回）
// const clearTable = ()=>{
//     showAddButton.value = false;
//     attrArr.value = []
// }
</script>

<style scoped lang="scss"></style>

<!-- 不使用pinia的属性table显示（不包含添加属性功能） -->
<!-- <Category :sendCategory="getCategory" @clearSelect="clearTable" />
<el-card style="margin: 10px 0;">
    <el-button type="primary" icon="Plus" :disabled="showAddButton">添加属性</el-button>
    <el-table :data="attrArr" style="margin: 10px 0;" border>
        <el-table-column label="序号" type="index" width="80px" align="center"></el-table-column>
        <el-table-column label="属性名称" prop="attrName" width="120px"></el-table-column>
        <el-table-column label="属性值名称">
            <template #="{ row, index }">
                <el-tag v-for="(attr, index) in row.attrValueList" :key="attr.id" type="primary" style="margin: 5px">
                    {{ attr.valueName }}</el-tag>
            </template>
        </el-table-column>
        <el-table-column label="操作" width="120px">
            <template #="{ row, index }">
                <el-button type="warning" size="small" icon="Edit"></el-button>
                <el-button type="danger" size="small" icon="Delete"></el-button>
            </template>
        </el-table-column>
    </el-table>
</el-card> -->